package com.sec.etech.ism.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.sec.etech.ism.service.MaterialNoLogService;
import com.sec.etech.ism.model.IsmAppSetting;
import com.sec.etech.ism.model.IsmServiceDef;
import com.sec.etech.ism.service.*;
import com.sec.etech.ism.util.SapSignatureUtil;
import lombok.extern.slf4j.Slf4j;
import org.openbpm.base.core.util.StringUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class IsmCreateMaterialNoServiceImpl implements IsmMethodService {
    @Resource
    JdbcTemplate jdbcTemplate;
    @Resource
    IsmAppSettingService ismAppSettingService;
    @Resource
    IsmTaskService ismTaskService;
    @Resource
    IsmServiceDefService ismServiceDefService;
    @Resource
    IsmTaskLogService ismTaskLogService;
    @Resource
    MaterialNoLogService materialNoLogService;
    @Resource
    IsmCommonService ismCommonService;

    public IsmCreateMaterialNoServiceImpl(){}

    @Override
    public JSONObject call(String sysCode, String serviceCode, JSONObject businessParams) throws Exception{
        JSONObject result = new JSONObject();
        String msg = this.createMaterialNo(sysCode, serviceCode, businessParams);
        result.put("flag", msg);
        result.put("msg", msg);
        return result;
    }

    /**
     * 调用SAp接口批量获取零件/部套物料号
     * @param sysCode
     * @param serviceCode
     * @param busObj
     * @return
     */
    private String createMaterialNo(String sysCode, String serviceCode, JSONObject busObj) {
        Map<String, String> logMap = new HashMap<>(5);
        //服务信息
        IsmServiceDef serviceDef = null;
        try {
            serviceDef = ismServiceDefService.getByCode(serviceCode);
            //调用的应用信息
            IsmAppSetting appSetting = ismAppSettingService.getByCode(sysCode);

            String url = ismCommonService.getSapPreUrl(appSetting.getAppAddress(), appSetting.getAppConfig()) + "/ZPLM_BADI_CREATMATER_LIST";
            List<Map<String, Object>> partsOrComList = null;
            Integer busType = busObj.getInteger("busType");//1-部套，2-零件，3-毛坯物料号，4-跟配件，5-精加工，6-自定义类型
            if (busType == 1) {//部套
                if (busObj.containsKey("ordersid")) {//机组清单中的部套
                    String sql = "select t2.componentid id, t2.component_SAPnum SAPnum, t2.componentnum num, t2.componentname `name`, t2.component_type businesstype " +
                            "from proj_orders_component t1, prod_component t2 " +
                            "where t1.componentid=t2.componentid and t1.componentid>0 and t1.active=1 " +
                            " and t2.componentnum not like 'TEMP%' and t1.ordersid=? ";
                    if (busObj.get("reCall") == null || busObj.getInteger("reCall").intValue() == 0) {
                        sql = sql + " and (t2.component_SAPnum is null or t2.component_SAPnum='')";
                    }
                    partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("ordersid"));
                } else if (busObj.containsKey("componentid")) {//单个部套（修改单、管理员操作）
                    String sql = "select componentid id, component_SAPnum SAPnum, componentnum num, componentname `name`, component_type businesstype " +
                            "from prod_component where componentid=? and componentnum not like 'TEMP%' ";
                    if (busObj.get("reCall") == null || busObj.getInteger("reCall").intValue() == 0) {
                        sql = sql + " and (component_SAPnum is null or component_SAPnum='') ";
                    }
                    partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("componentid"));
                } else if (busObj.containsKey("componentids")) {//批量部套（修改单、管理员操作）
                    String sql = "select componentid id, component_SAPnum SAPnum, componentnum num, componentname `name`, component_type businesstype " +
                            "from prod_component where componentid in({}) and componentnum not like 'TEMP%' ";
                    if (busObj.get("reCall") == null || busObj.getInteger("reCall").intValue() == 0) {
                        sql = sql + " and (component_SAPnum is null or component_SAPnum='')";
                    }
                    partsOrComList = jdbcTemplate.queryForList(StrUtil.format(sql, busObj.getString("componentids")));
                }
            } else if (busType == 2) {//零件
                if (busObj.containsKey("componentid")) {//部套下的原创零件
                    String sql = "select partsid id, parts_SAPnum SAPnum, partsnum num, partsname `name`, weight, parts_type businesstype " +
                            "from prod_parts where active=1 and (drawing_logo=0 or drawing_logo is null) and original_componentid=? ";
                    if (busObj.get("reCall") == null || busObj.getInteger("reCall").intValue() == 0) {
                        sql = sql + " and (parts_SAPnum is null or parts_SAPnum='')";
                    }
                    partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("componentid"));
                } else if (busObj.containsKey("partsid")) {
                    String sql = "select partsid id, parts_SAPnum SAPnum, partsnum num, partsname `name`, weight, parts_type businesstype " +
                            "from prod_parts where active=1 and (drawing_logo=0 or drawing_logo is null) and partsid=? ";
                    if (busObj.get("reCall") == null || busObj.getInteger("reCall").intValue() == 0) {
                        sql = sql + " and (parts_SAPnum is null or parts_SAPnum='')";
                    }
                    partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("partsid"));
                } else if (busObj.containsKey("partsids")) {
                    String sql = "select partsid id, parts_SAPnum SAPnum, partsnum num, partsname `name`, weight, parts_type businesstype " +
                            "from prod_parts where active=1 and (drawing_logo=0 or drawing_logo is null) and partsid in({}) ";
                    if (busObj.get("reCall") == null || busObj.getInteger("reCall").intValue() == 0) {
                        sql = sql + " and (parts_SAPnum is null or parts_SAPnum='')";
                    }
                    partsOrComList = jdbcTemplate.queryForList(StrUtil.format(sql, busObj.getString("partsids")));
                }
            } else if (busType == 3) {//零件毛坯物料号
                if (busObj.containsKey("componentid")) {//单个部套下的原创零件
                    String sql = "select t1.partsid id, t1.billet_SAPnum SAPnum, t1.parts_SAPnum, t1.partsnum num, t1.partsname `name`, t1.parts_type businesstype, " +
                            "t1.detaillist, t1.unit_parts_gross_weight, t2.`name` attributeName " +
                            "from prod_parts t1 left join prod_parts_z_attribute t2 on t1.partsAttributeid=t2.partsAttributeid " +
                            "where t1.active=1 and t1.original_componentid=? and t1.billet_SAPnum is not null and t1.billet_SAPnum!=''";
                    partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("componentid"));
                } else if (busObj.containsKey("partsid")) {//单个零件
                    String sql = "select t1.partsid id, t1.billet_SAPnum SAPnum, t1.parts_SAPnum, t1.partsnum num, t1.partsname `name`, t1.parts_type businesstype, " +
                            "t1.detaillist, t1.unit_parts_gross_weight, t2.`name` attributeName from prod_parts t1 " +
                            "left join prod_parts_z_attribute t2 on t1.partsAttributeid=t2.partsAttributeid " +
                            "where t1.active=1 and t1.partsid=? and t1.billet_SAPnum is not null and t1.billet_SAPnum!=''";
                    partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("partsid"));
                } else if (busObj.containsKey("partsids")) {//批量零件
                    String sql = "select t1.partsid id, t1.billet_SAPnum SAPnum, t1.parts_SAPnum, t1.partsnum num, t1.partsname `name`, t1.parts_type businesstype, " +
                            "t1.detaillist, t1.unit_parts_gross_weight, t2.`name` attributeName from prod_parts t1 " +
                            "left join prod_parts_z_attribute t2 on t1.partsAttributeid=t2.partsAttributeid " +
                            "where t1.active=1 and t1.partsid in({}) and t1.billet_SAPnum is not null and t1.billet_SAPnum!=''";
                    partsOrComList = jdbcTemplate.queryForList(StrUtil.format(sql, busObj.getString("partsids")));
                }
            } else if (busType == 4 || busType == 5) {//部套额外物料号——跟配件/精加工
                String sql = "select a.componentid id, b.parts_SAPnum SAPnum, b.parts_SAPnum, a.componentnum num, a.componentname `name`, a.component_type businesstype " +
                        "from prod_component as a,prod_parts as b where a.componentid=? and a.componentnum not like 'TEMP%' " +
                        "and b.original_componentid=a.componentid and b.active=1 and b.generalview=1 and b.parts_SAPnum is not null ";
                if (busObj.get("reCall") == null || busObj.getInteger("reCall").intValue() == 0) {
                    sql = sql + " and (a.component_SAPnum is null or a.component_SAPnum='') ";
                }
                sql = sql + " order by b.partsnum asc limit 1";
                partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("componentid"));
            } else if (busType == 6) {//自定义类型
                if (busObj.containsKey("ruleKey") && (busObj.containsKey("ruleName") || busObj.containsKey("description"))) {
                    if (busObj.containsKey("componentid")) {//单个部套
                        String sql = "select componentid id, component_SAPnum SAPnum, componentnum num, componentname `name`, component_type businesstype " +
                                "from prod_component where componentid=? and componentnum not like 'TEMP%' ";
                        partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("componentid"));
                    } else if (busObj.containsKey("partsid")) {//单个零件
                        String sql = "select partsid id, parts_SAPnum SAPnum, partsnum num, partsname `name`, weight, parts_type businesstype " +
                                "from prod_parts where active=1 and (drawing_logo=0 or drawing_logo is null) and partsid=? ";
                        partsOrComList = jdbcTemplate.queryForList(sql, busObj.getString("partsid"));
                    }
                }
            }
            if (partsOrComList == null || partsOrComList.size() == 0) {
                return "success";
            }
            String msg = "success";
            //分组执行，10条一组调用一次接口
            int count = partsOrComList == null ? 0 : partsOrComList.size();
            for (int i = 0; i <= Math.floor(count / 10); i++) {
                JSONObject sapParams = new JSONObject();
                Set<JSONObject> zDocumentList = new HashSet<>();
                Set<JSONObject> zallocValuesNumList = null;
                Set<JSONObject> zallocValuesCharList = new HashSet<>();
                Set<JSONObject> zzDocumentDescList = new HashSet<>();
                Map<String, Map<String, Object>> numMap = new HashMap<>();
                List<Map<String, Object>> subList = partsOrComList.subList(i * 10, (i + 1) * 10 > count ? count : (i + 1) * 10);
                for (Map<String, Object> map : subList) {
                    String documentNum = null;
                    if (busType == 3) {
                        documentNum = map.get("SAPnum").toString();
                    } else if (busType == 4) {
                        documentNum = map.get("SAPnum").toString();
                        documentNum = documentNum.substring(0, documentNum.length() - 1) + "K";
                    } else if (busType == 5) {
                        documentNum = map.get("SAPnum").toString();
                        documentNum = documentNum.substring(0, documentNum.length() - 1) + "J";
                    } else if (busType == 6) {
                        documentNum = map.get("SAPnum").toString();
                        documentNum = documentNum.substring(0, documentNum.length() - 1) + busObj.getString("ruleKey");
                    } else {
                        documentNum = map.get("num").toString();
                    }
                    numMap.put(documentNum, map);
                    //部套/零件图号
                    JSONObject zDocumentObj = new JSONObject();
                    zDocumentObj.put("DOCUMENTNUMBER", documentNum);
                    zDocumentObj.put("AUTHORITYGROUP", "1303");
                    if (busType == 3 || busType == 4 || busType == 5 || busType == 6) {
                        zDocumentObj.put("MATERIAL", documentNum);
                    }
                    zDocumentList.add(zDocumentObj);
                    JSONObject zDocumentObj1 = new JSONObject();
                    zDocumentObj1.put("DOCUMENTNUMBER", documentNum);
                    zDocumentObj1.put("AUTHORITYGROUP", "1301");
                    if (busType == 3 || busType == 4 || busType == 5 || busType == 6) {
                        zDocumentObj1.put("MATERIAL", documentNum);
                    }
                    zDocumentList.add(zDocumentObj1);
                    //零件净重
                    /*if(busType==2 && StringUtil.isNotEmpty(map.get("weight"))) {
                        zallocValuesNumList = new HashSet<>();
                        JSONObject zallNumObj = new JSONObject();
                        zallNumObj.put("DOCUMENTNUMBER", documentNum);
                        zallNumObj.put("CHARACT", "PLM_NETWEIGHT");
                        zallNumObj.put("VALUE_FROM", map.get("weight"));
                        zallocValuesNumList.add(zallNumObj);
                    }else if(busType==3) {//毛坯
                        zallocValuesNumList = new HashSet<>();
                        JSONObject zallNumObj = new JSONObject();
                        zallNumObj.put("DOCUMENTNUMBER", documentNum);
                        zallNumObj.put("CHARACT", "PLM_NETWEIGHT");
                        zallNumObj.put("VALUE_FROM", map.get("unit_parts_gross_weight"));
                        zallocValuesNumList.add(zallNumObj);
                    }*/
                    //不详，默认值
                    JSONObject zallocCharObj = new JSONObject();
                    zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                    zallocCharObj.put("CHARACT", "PLM_MATERIALTYPE");
                    zallocCharObj.put("VALUE_NEUTRAL", "SECD");//物料的类型，默认值
                    zallocValuesCharList.add(zallocCharObj);
                    //物料组
                    zallocCharObj = new JSONObject();
                    zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                    zallocCharObj.put("CHARACT", "PLM_MATERIALGROUP");
                    if (busType == 1 || busType == 2) {//部套、零件
                        zallocCharObj.put("VALUE_NEUTRAL", ismCommonService.getPartsMaterialGroup(map.get("name").toString(),
                                map.get("businesstype") != null ? map.get("businesstype").toString() : null));
                    } else if (busType == 3) {//毛坯
                        String attributeName = map.get("attributeName") != null ? map.get("attributeName").toString() : null;
                        String billetSAPnum = map.get("billet_SAPnum") != null ? map.get("billet_SAPnum").toString() : null;
                        zallocCharObj.put("VALUE_NEUTRAL", ismCommonService.getBilletMaterialGroup(attributeName,
                                billetSAPnum, map.get("detaillist") != null ? (Integer) map.get("detaillist") : null,
                                map.get("businesstype") != null ? map.get("businesstype").toString() : null));
                    } else if (busType == 4 || busType == 5 || busType == 6) {
                        zallocCharObj.put("VALUE_NEUTRAL", "B020");
                    }
                    zallocValuesCharList.add(zallocCharObj);
                    //基本计量单位，部套的为“套”，零件为“EA”（个），毛坯物料号为...
                    zallocCharObj = new JSONObject();
                    zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                    zallocCharObj.put("CHARACT", "PLM_BASEUNIT");
                    if (busType == 1) {
                        zallocCharObj.put("VALUE_NEUTRAL", "套");
                    } else if (busType == 2 || busType == 3 || busType == 4 || busType == 5) {
                        zallocCharObj.put("VALUE_NEUTRAL", "EA");
                    } else if (busType == 6){
                        if(busObj.containsKey("componentid")){
                            zallocCharObj.put("VALUE_NEUTRAL", "套");
                        } else {
                            zallocCharObj.put("VALUE_NEUTRAL", "EA");
                        }
                    }
                    zallocValuesCharList.add(zallocCharObj);
                    //产品组，默认值
                    zallocCharObj = new JSONObject();
                    zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                    zallocCharObj.put("CHARACT", "PLM_PRODUCEGROUP");
                    zallocCharObj.put("VALUE_NEUTRAL", "50");
                    zallocValuesCharList.add(zallocCharObj);
                    //上汽物料编码规则
                    zallocCharObj = new JSONObject();
                    zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                    zallocCharObj.put("CHARACT", "PLM_DRAWINGTYPE");
                    if (busType == 3) {
                        zallocCharObj.put("VALUE_NEUTRAL", "04");
                    } else if (busType == 4 || busType == 5 || busType == 6) {
                        zallocCharObj.put("VALUE_NEUTRAL", "01");
                    } else {
                        zallocCharObj.put("VALUE_NEUTRAL", ismCommonService.getDrawingType(map.get("num").toString(),
                                map.get("businesstype") != null ? map.get("businesstype").toString() : null));
                    }
                    zallocValuesCharList.add(zallocCharObj);
                    //项目类别
                    zallocCharObj = new JSONObject();
                    zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                    zallocCharObj.put("CHARACT", "PLM_ITEMCATEGORY");
                    zallocCharObj.put("VALUE_NEUTRAL", "L");
                    zallocValuesCharList.add(zallocCharObj);
                    //重量单位，“T0”“KG”  公吨 千克
                    zallocCharObj = new JSONObject();
                    zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                    zallocCharObj.put("CHARACT", "PLM_WEIGHT_UNIT");
                    zallocCharObj.put("VALUE_NEUTRAL", "KG");
                    zallocValuesCharList.add(zallocCharObj);

                    if (busType == 3 || busType == 4 || busType == 5 || busType == 6) {//毛坯或者跟配件或者精加工或者自定义
                        zallocCharObj = new JSONObject();
                        zallocCharObj.put("DOCUMENTNUMBER", documentNum);
                        zallocCharObj.put("CHARACT", "ZOM01");
                        zallocCharObj.put("VALUE_NEUTRAL", map.get("parts_SAPnum"));
                        zallocValuesCharList.add(zallocCharObj);
                    }

                    //ZH 部套/零件名称
                    JSONObject zzDocumentDescObj = new JSONObject();
                    zzDocumentDescObj.put("DOCUMENTNUMBER", documentNum);
                    zzDocumentDescObj.put("LANGUAGE_ISO", "ZH");
                    if (busType == 1 || busType == 2) {//零件
                        zzDocumentDescObj.put("DESCRIPTION", map.get("name"));
                    } else if (busType == 3) {//毛坯
                        zzDocumentDescObj.put("DESCRIPTION", map.get("num").toString() + " " + map.get("name").toString());
                    } else if (busType == 4) {//部套额外物料号——跟配件
                        zzDocumentDescObj.put("DESCRIPTION", map.get("num").toString() + "跟配件 " + map.get("name").toString());
                    } else if (busType == 5) {//部套额外物料号——精加工
                        zzDocumentDescObj.put("DESCRIPTION", map.get("num").toString() + "精加工 " + map.get("name").toString());
                    } else if (busType == 6) {//部套额外物料号——自定义
                        if (busObj.containsKey("description")){
                            zzDocumentDescObj.put("DESCRIPTION", busObj.getString("description"));
                        } else {
                            zzDocumentDescObj.put("DESCRIPTION", map.get("num").toString() + busObj.getString("ruleName") + " " + map.get("name").toString());
                        }
                    }
                    zzDocumentDescList.add(zzDocumentDescObj);
                }
                sapParams.put("ZDOCUMENT", zDocumentList);
                sapParams.put("ZALLOC_VALUES_NUM", zallocValuesNumList);
                sapParams.put("ZALLOC_VALUES_CHAR", zallocValuesCharList);
                sapParams.put("ZZDOCUMENTDESCRIPTIONS", zzDocumentDescList);

                JSONObject dataObj = this.checkSapResult(url, sapParams, serviceDef, appSetting.getAppKey2(),
                        null, busObj.toJSONString(), sysCode, "ZPLM_BADI_CREATMATER_LIST", logMap);
                if (dataObj != null && dataObj.containsKey("RETURNS")) {
                    List<JSONObject> returnList = (List<JSONObject>) dataObj.get("RETURNS");
                    if (returnList != null && returnList.size() > 0) {
                        for (JSONObject object : returnList) {
                            String materialNo = object.getString("ID");
                            if (StringUtil.isNotEmpty(materialNo)) {
                                //去除前面无效0   .replaceAll("^(0+)", "") 或者 .replaceFirst("^0*", "")
                                materialNo = materialNo.replaceFirst("^0*", "");
                            }
                            String num = object.getString("MESSAGE_V2");
                            Map<String, Object> busMap = null;
                            if (busType == 3 || busType == 4 || busType == 5 || busType == 6) {
                                busMap = numMap.get(materialNo);
                            } else {
                                busMap = numMap.get(num);
                            }
                            //保存或者更新物料号记录表
                            materialNoLogService.saveOrUpdateByCreate(Long.parseLong(busMap.get("id").toString()),
                                    busType, busObj.toJSONString(), materialNo, num, busMap.get("name").toString());
                        }
                    }
                }
                if (dataObj == null) {
                    msg = "批量获取零件/部套物料号接口异常，请联系管理员处理！";
                } else if (StringUtil.isNotEmpty(dataObj.getString("message"))) {
                    msg = dataObj.getString("message");
                }
            }
            return msg;
        } catch (Exception e) {
            log.error("批量获取零件/部套物料号接口异常。serviceDef.getCode()={}，serviceDef.getName()={}，logMap={}",
                    serviceDef.getCode(), serviceDef.getName(), logMap);
            e.printStackTrace();
            return "批量获取零件/部套物料号接口异常，请联系管理员处理！";
        }
    }

    //检查sap返回结果，获取返回数据
    private JSONObject checkSapResult(String url, JSONObject sapParams, IsmServiceDef serviceDef, String appKey, String businessCode,
                                      String businessParams, String sysCode, String methodName, Map<String, String> logMap) throws Exception{

        JSONObject bodyObj = SapSignatureUtil.buildRequestParams(sapParams, appKey);
        String body = JSONObject.toJSONString(bodyObj);
        int timeout = JSONObject.parseObject(serviceDef.getParams()).getInteger("timeout");
        long startTime = System.currentTimeMillis();
        String result = HttpUtil.post(url, body, timeout*60*1000);
        log.info("SAP系统{}接口耗时：{}ms。", methodName, System.currentTimeMillis() - startTime);
        JSONObject resultObj = JSONObject.parseObject(result);

        JSONObject taskObj = new JSONObject();
        taskObj.put("sysCode", sysCode);
        taskObj.put("serviceCode", serviceDef.getCode());
        taskObj.put("methodName", methodName);
        taskObj.put("businessCode", businessCode);
        taskObj.put("businessParams", businessParams);
        taskObj.put("resultObj", resultObj);
        Long taskId = ismTaskService.checkAndSave(taskObj);
        //保存接口调用日志
        JSONObject logObj = new JSONObject();
        logObj.put("task_id", taskId);
        logObj.put("service_code", serviceDef.getCode());
        logObj.put("service_name", serviceDef.getName());
        logObj.put("method_name", methodName);
        logObj.put("request_url", url);
        logObj.put("input_json", bodyObj);
        logObj.put("output_json", result);
        JSONObject dataObj = resultObj!=null ? resultObj.getJSONObject("data") : null;
        String message = null;
        if(resultObj==null || !resultObj.getBoolean("success")) {
            message = resultObj!=null ? resultObj.getString("message") : "接口无返回数据，请检查接口和网络！";
        }else if(dataObj!=null && StringUtil.isNotEmpty(dataObj.getString("RETURN"))) {
            message = dataObj.getJSONObject("RETURN").getString("MESSAGE");
        }else if(dataObj!=null && StringUtil.isNotEmpty(dataObj.getString("RET"))) {
            message = dataObj.getJSONObject("RET").getString("MESSAGE");
        }
        if(taskId!=null && taskId>0) {
            message = StringUtil.isNotEmpty(message) ? message : "生成物料号失败，请联系管理员！";
            logObj.put("message", message);
        }
        logMap.put("input", body);
        logMap.put("output", result);
        ismTaskLogService.saveLog(logObj);
        if(dataObj!=null) {
            dataObj.put("message", message);
        }
        return dataObj;
    }

    @Override
    public String methodName(){
        return "createMaterialNo";
    }
}
